

namespace NodeBasedSkillEditor.Model.Node.RT
{
    public class Node_ForLoop_RT : RT_Node
    {
        public RT_FlowPort FlowIn_RT;

        public RT_SingleValuePort Start_RT;

        public RT_SingleValuePort End_RT;

        public RT_FlowPort Loop_RT;

        public RT_SingleValuePort Index_RT;

        public RT_FlowPort AfterLoop_RT;

        public Node_ForLoop_RT(Node_ForLoop sourceData, RT_DAG parentDag) : base(sourceData, parentDag)
        {
            FlowIn_RT = new RT_FlowPort(EPortIOType.Input, sourceData.FlowIn, this);

            Start_RT = new RT_SingleValuePort(EPortIOType.Input, sourceData.Start, this);

            End_RT = new RT_SingleValuePort(EPortIOType.Input, sourceData.End, this);

            Loop_RT = new RT_FlowPort(EPortIOType.Output, sourceData.Loop, this);

            Index_RT = new RT_SingleValuePort(EPortIOType.Output, sourceData.Index, this);
            Index_RT.OnGetValue = GetIndex;

            AfterLoop_RT = new RT_FlowPort(EPortIOType.Output, sourceData.AfterLoop, this);

        }

        public AValue GetIndex(DAG_Executor executor)
        {
            ForLoop_Info info = executor.GetExeInfoOfNode(this) as ForLoop_Info;
            if (info != null)
            {
                Index_RT.SourceValue.SetInteger(info.CurrentStep);
            }
            return Index_RT.SourceValue;
        }

        public override (EDagExeState, RT_Node) ForewardExecute(DAG_Executor executor)
        {
            if (Loop_RT.LinkedPortInWorkingDirection != null)
            {
                int start = Start_RT.GetValue(executor).ToInteger().Item2;
                int end = End_RT.GetValue(executor).ToInteger().Item2;
                if (start < end)
                {
                    var info = new ForLoop_Info() { CurrentStep = start };
                    executor.SetExeInfoOfNode(this, info);
                    return TryForewardByPort(Loop_RT);
                }
            }
            return TryForewardByPort(AfterLoop_RT);
        }

        public override (EDagExeState, RT_Node) BackwardExecute(DAG_Executor executor)
        {
            if (Loop_RT.LinkedPortInWorkingDirection != null)
            {
                var info = executor.GetExeInfoOfNode(this) as ForLoop_Info;
                if (info != null)
                {
                    int end = End_RT.GetValue(executor).ToInteger().Item2;
                    info.CurrentStep++;
                    if (info.CurrentStep < end)
                    {
                        return TryForewardByPort(Loop_RT);
                    }
                    else if (info.CurrentStep == end)
                    {
                        return TryForewardByPort(AfterLoop_RT);
                    }
                }
            }
            return (EDagExeState.Backward, null);
        }
    }

    public class ForLoop_Info : RT_NodeExeInfo
    {
        public int CurrentStep;
    }
}